package com.jstyle.jclife.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.LatLng;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.FitnessOptions;
import com.google.android.gms.fitness.data.DataType;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.jstyle.blesdk.model.ExerciseMode;
import com.jstyle.jclife.NetWork.NetWorkUtil;
import com.jstyle.jclife.R;
import com.jstyle.jclife.app.MyApplication;
import com.jstyle.jclife.daoManager.GpsDataDaoManager;
import com.jstyle.jclife.daoManager.PathRecordDaoManager;
import com.jstyle.jclife.model.Device1755;
import com.jstyle.jclife.model.Device1860;
import com.jstyle.jclife.model.FindInfo;
import com.jstyle.jclife.model.GpsData;
import com.jstyle.jclife.model.PathRecord;
import com.jstyle.jclife.model.StravasTokenInfo;
import com.jstyle.jclife.model.StravasUploads;
import com.jstyle.jclife.utils.DateUtil;
import com.jstyle.jclife.utils.ImageUtils;
import com.jstyle.jclife.utils.PermissionsUtil;
import com.jstyle.jclife.utils.RxBus;
import com.jstyle.jclife.utils.SharedPreferenceUtils;
import com.jstyle.jclife.utils.Utils;

import org.alternativevision.gpx.GPXParser;
import org.alternativevision.gpx.beans.GPX;
import org.alternativevision.gpx.beans.Route;
import org.alternativevision.gpx.beans.Track;
import org.alternativevision.gpx.beans.Waypoint;

import java.io.File;
import java.io.FileOutputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;

public class ThirdDataActivity extends BaseActivity {

    @BindView(R.id.button_googleFit)
    Button buttonGoogleFit;
    @BindView(R.id.button_strava)
    TextView buttonStrava;
    @BindView(R.id.llbb)
    RelativeLayout llbb;


    private GoogleSignInAccount account;
    private int GOOGLE_SIGN_IN = 122;
    private static final String TAG = "ThirdDataActivity";
    private FitnessOptions fitnessOptions;
    private int GOOGLE_FIT_PERMISSIONS_REQUEST_CODE = 123;



    //strava
    int status=0;//当前是否同后台数据同步，0没有上传过数据，1后台已经有数据需要最新数据同步
    String begintime=null;
    private int strava = 124;
    Upload up;
    String uptime;
    public static int count = 0;
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        ThirdDataActivity.count = count;
    }

    @SuppressLint("CheckResult")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third_data);
        ButterKnife.bind(this);
        if (MyApplication.getJstyleDevice() instanceof Device1755 ) {
            PermissionsUtil.requestPermissions(ThirdDataActivity.this,null,Manifest.permission.WRITE_EXTERNAL_STORAGE);
            llbb.setVisibility(View.VISIBLE);
            RxBus.getInstance().toObservable(Message.class).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Message>() {
                @Override
                public void accept(Message bleData) {
                    switch (bleData.what) {
                        case 0:
                            if (Utils.getRunningActivityName(ThirdDataActivity.this).contains("ThirdDataActivity")) {
                                buttonStrava.setText("Connected");
                            }
                            break;
                        case 1:
                            if (Utils.getRunningActivityName(ThirdDataActivity.this).contains("ThirdDataActivity")) {
                                buttonStrava.setText(bleData.obj.toString());
                            }
                            break;
                    }

                }
            });
        }
        init();
    }

    private void init() {
        fitnessOptions = FitnessOptions.builder()
                .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_WRITE)
                .addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_WRITE)
                .addDataType(DataType.TYPE_CALORIES_EXPENDED, FitnessOptions.ACCESS_WRITE)
                .addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_WRITE)
                .addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_READ)
                .addDataType(DataType.TYPE_HEART_POINTS, FitnessOptions.ACCESS_WRITE)
                .addDataType(DataType.TYPE_HEART_POINTS, FitnessOptions.ACCESS_READ)
                .build();
        account = GoogleSignIn.getLastSignedInAccount(this);
        if (account != null) {
            if (GoogleSignIn.hasPermissions(account, fitnessOptions)) {
                buttonGoogleFit.setText("Connected");
            }
        }
    }

    @OnClick({R.id.button_googleFit, R.id.llbb})
    public void onViewClicked(View view) {
        if(Utils.isFastClick()){return;}
        switch (view.getId()) {
            case R.id.button_googleFit:
                connectGoogle();
                break;
            case R.id.llbb:
                String address= SharedPreferenceUtils.getSpString(SharedPreferenceUtils.KEY_ADDRESS);
                if(TextUtils.isEmpty(address)){
                    showToast(getResources().getString(R.string.not_pair_device));
                    return;}
                List<PathRecord>   pathRecordList = PathRecordDaoManager.getAllPathRecordByMode();
                if(pathRecordList.size()==0){
                    showToast(getResources().getString(R.string.notnewdata));
                }else{
                    //是否有网络
                    if (Utils.checkNetWork(this)) {
                        if (getCount() == 0&&!buttonStrava.getText().toString().equals(getString(R.string.Data_Synchronizing))) {
                            findtime();
                        } else {
                            showToast(getResources().getString(R.string.Data_Synchronizing));
                        }
                    } else {
                        showToast(this.getString(R.string.Network_not_availa));
                    }

                }

                break;
        }
    }



    public void connectGoogle() {
        try {
            //如果已经登录过google账号。则可以拿到账号
            account = GoogleSignIn.getLastSignedInAccount(this);
            if (account == null) {
                //没有。则要登录
                signIn();
            } else {
                //有，则要订阅
                Subscribe();
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    private void signIn() {
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail().build();
        GoogleSignInClient mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, GOOGLE_SIGN_IN);
    }

    private void Subscribe() {
        account = GoogleSignIn.getLastSignedInAccount(this);
        if (account == null) {
            return;
        }
        //判断是否有写入数据的权限，这个会弹出授权写入数据的弹框
        if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) {
            GoogleSignIn.requestPermissions(
                    this, // your activity
                    GOOGLE_FIT_PERMISSIONS_REQUEST_CODE,
                    account,
                    fitnessOptions);
        } else {
            subscriptionData();
        }
    }

    private void subscriptionData() {
        subscribe(DataType.TYPE_STEP_COUNT_DELTA);// 订阅步数
        subscribe(DataType.TYPE_DISTANCE_DELTA);//
        PermissionsUtil.requestPermissions(this, new PermissionsUtil.PermissionListener() {
            @Override
            public void granted(String name) {
                subscribe(DataType.TYPE_HEART_RATE_BPM);//
            }

            @Override
            public void NeverAskAgain() {

            }

            @Override
            public void disallow(String name) {

            }
        }, Manifest.permission.BODY_SENSORS);


    }

    private void subscribe(final DataType dataType) {
        GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
        if (account == null) {
            return;
        }
        Fitness.getRecordingClient(this, GoogleSignIn.getLastSignedInAccount(this))
                .subscribe(dataType)
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        //每订阅成功一个，会回调这个方法

                        Log.i(TAG, "onSuccess: " + dataType.getName());
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.i(TAG, "onFailure: " + e.getMessage());
                    }
                });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.i(TAG, "onActivityResult: " + requestCode + " " + resultCode);
        if (resultCode == RESULT_OK) {
            if (requestCode == GOOGLE_FIT_PERMISSIONS_REQUEST_CODE) {
                subscriptionData();
            } else if (requestCode == GOOGLE_SIGN_IN) {
                Subscribe();
            }
        }else if (resultCode == strava) {
            if(null!=data&&!TextUtils.isEmpty(data.getStringExtra("code"))){
                buttonStrava.setText(getString(R.string.Data_Synchronizing));
                //授权
                status=0;
                Gettoken(data.getStringExtra("code").trim());
                Log.e("code",data.getStringExtra("code").trim());
            }

        }
    }


    private class Upload extends Thread {
        StravasTokenInfo stravasTokenInfoa;
        public Upload(StravasTokenInfo stravasTokenInfo) {
            this.stravasTokenInfoa = stravasTokenInfo;
        }
        @Override
        public void run() {
            DataInfo(stravasTokenInfoa);
        }
    }




    private void stravaLogin() {
        Intent intent = new Intent(ThirdDataActivity.this, StravaWebActivity.class);
        startActivityForResult(intent, strava);
    }

    private void findtime() {
        // stravaLogin();
        String address= SharedPreferenceUtils.getSpString(SharedPreferenceUtils.KEY_ADDRESS);
        Map<String, Object> map = new HashMap<>();
        map.put("uid", NetWorkUtil.getUserId());
        map.put("mac", address);
        NetWorkUtil.getInstance().getJstyleApi().queryLastTime(map).
                subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<FindInfo>() {
            @Override
            public void onSubscribe(Disposable d) {
            }

            @Override
            public void onNext(FindInfo activitvtiesData) {
                //查询保存数据的时间是否与本地一致
                final List<PathRecord> pathRecordList = PathRecordDaoManager.getAllPathRecordByMode();
                if (pathRecordList.size() != 0) {
                    if(null == activitvtiesData.getData()){
                        status=0;
                        uptime = "20" + pathRecordList.get(0).getMDate().replace(".", "-");
                    }else{
                        status=1;
                        begintime=((activitvtiesData.getData().replace("-", ".")).substring(2)).split(" ")[0];
                        if(null!=begintime&&null!=PathRecordDaoManager.getLastPathRecord()&&null!=PathRecordDaoManager.getLastPathRecord().getMDate()){
                            String endtime=PathRecordDaoManager.getLastPathRecord().getMDate();
                            final List<PathRecord> pathRecordListA   = PathRecordDaoManager.getAllPathRecordByModefortime(begintime,endtime);
                            uptime = "20" + pathRecordListA.get(0).getMDate().replace(".", "-");
                        }
                    }
                    if (null == activitvtiesData.getData() || !activitvtiesData.getData().equals(uptime)) {
                        stravaLogin();
                    } else {
                        showToast(getResources().getString(R.string.notnewdata));
                    }
                } else {
                    showToast(ThirdDataActivity.this.getString(R.string.notnewdata));
                }
            }

            @Override
            public void onError(Throwable e) {
                showToast(ThirdDataActivity.this.getString(R.string.connection_timeout));
            }

            @Override
            public void onComplete() {
            }
        });
    }


    private void savetime(String time) {
        String address= SharedPreferenceUtils.getSpString(SharedPreferenceUtils.KEY_ADDRESS);
        if(TextUtils.isEmpty(address)){return;}
        Map<String, Object> map = new HashMap<>();
        map.put("uid", NetWorkUtil.getUserId());
        map.put("time", time);
        map.put("mac", address);
        NetWorkUtil.getInstance().getJstyleApi().saveLastTime(map).
                subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<FindInfo>() {
            @Override
            public void onSubscribe(Disposable d) { }
            @Override
            public void onNext(FindInfo activitvtiesData) { }
            @Override
            public void onError(Throwable e) { }
            @Override
            public void onComplete() { }
        });
    }



    private void Gettoken(String code) {
        Map<String, Object> map = new HashMap<>();
        map.put("client_id", "37590");
        map.put("client_secret", "683d5a9f30ba360956142ca03b58f9388c19efb6");
        map.put("grant_type", "authorization_code");
        map.put("code", code);
        NetWorkUtil.getInstance().getJstyleApi().Strvastoken(map).
                subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<StravasTokenInfo>() {
            @Override
            public void onSubscribe(Disposable d) { }
            @Override
            public void onNext(StravasTokenInfo activitvtiesData) {
                this.onComplete();
                up = new Upload(activitvtiesData);
                up.start();
            }
            @Override
            public void onError(Throwable e) { }
            @Override
            public void onComplete() { }
        });
    }



    /**
     * 解析数据
     * 生成Gpx文件
     */
    LatLng latLng=null;
    LatLng lastLng=null;
    private void DataInfo(StravasTokenInfo activitvtiesData) {
        final List<PathRecord> pathRecordList;
        if(0==status){
            pathRecordList = PathRecordDaoManager.getAllPathRecordByMode();
            uptime = "20" + pathRecordList.get(0).getMDate().replace(".", "-");
        }else{
            if(null!=begintime&&null!=PathRecordDaoManager.getLastPathRecord()&&null!=PathRecordDaoManager.getLastPathRecord().getMDate()){
                String endtime=PathRecordDaoManager.getLastPathRecord().getMDate();
                pathRecordList = PathRecordDaoManager.getAllPathRecordByModefortime(begintime,endtime);
                uptime = "20" + pathRecordList.get(0).getMDate().replace(".", "-");
            }else{
                pathRecordList = new ArrayList<>();
            }
        }

        if (pathRecordList.size() != 0) {
            int thecout = pathRecordList.size();
            for (int i = 0; i < thecout; i++) {
                String time = pathRecordList.get(i).getMDate();
                String duration = pathRecordList.get(i).getMDuration();
                long startL = DateUtil.getGpsDateLong(time);
                long endL = startL + Integer.valueOf(duration) * 1000;
                String endTime = DateUtil.getFormatTimeString(endL);
                ArrayList<Waypoint> wayPoints = new ArrayList<>();
                List<GpsData> gpsDataList = GpsDataDaoManager.getPathRecord(time, endTime);
                if (gpsDataList.size() == 0) {
                    Showinfo(thecout);
                } else {
                    long lastL = DateUtil.getGpsDateLong(time);

                    for (int j = 0; j < gpsDataList.size(); j++) {
                        if(null!=gpsDataList.get(j).getLatitudeString()){
                            String LatitudeString[] = gpsDataList.get(j).getLatitudeString().split(",");
                            String LongitudeString[] = gpsDataList.get(j).getLongitudeString().split(",");
                            Date timesa = DateUtil.getData("20" + gpsDataList.get(j).getDate());
                            //数据过滤
                            String date = gpsDataList.get(j).getDate();
                            long gpsStartL = DateUtil.getGpsDateLong(date);

                            for (int b = 0; b < 6; b++) {
                                if(null==latLng){//第一个点直接加入
                                    latLng=new LatLng(Double.valueOf(LatitudeString[b]),Double.valueOf(LongitudeString[b]));
                                    lastLng=new LatLng(Double.valueOf(LatitudeString[b]),Double.valueOf(LongitudeString[b]));
                                    Waypoint waypoint = new Waypoint();
                                    waypoint.setLatitude(Double.valueOf(LatitudeString[b]));
                                    waypoint.setLongitude(Double.valueOf(LongitudeString[b]));
                                    waypoint.setTime(timesa);
                                    wayPoints.add(waypoint);
                                }else{
                                    latLng=new LatLng(Double.valueOf(LatitudeString[b]),Double.valueOf(LongitudeString[b]));
                                    long durationb = (gpsStartL + b * 1000 - lastL) / 1000;
                                    double betweenDis = AMapUtils.calculateLineDistance(lastLng, latLng);
                                    if(betweenDis < 100 * durationb){
                                        lastLng=new LatLng(Double.valueOf(LatitudeString[b]),Double.valueOf(LongitudeString[b]));
                                        Waypoint waypoint = new Waypoint();
                                        waypoint.setLatitude(Double.valueOf(LatitudeString[b]));
                                        waypoint.setLongitude(Double.valueOf(LongitudeString[b]));
                                        waypoint.setTime(timesa);
                                        wayPoints.add(waypoint);
                                    }
                                }

                            }}
                    }
                    latLng=null;
                    lastLng=null;
                    //创建gpx文件夹
                    File ecgFile = new File(ImageUtils.GPXPath);
                    if (!ecgFile.exists()) {
                        ecgFile.mkdirs();
                    }
                    String name = pathRecordList.get(i).getExerciseMode() == ExerciseMode.Mode_RUN ? "run_" + DateUtil.getDataer("20" + pathRecordList.get(i).getMDate()).getTime() :
                            "ride_" + DateUtil.getDataer("20" + pathRecordList.get(i).getMDate()).getTime();
                    String filePath = ImageUtils.GPXPath + name + ".gpx";
                    File fileOut = new File(filePath);
                    try {
                        fileOut.createNewFile();//创建gpx文件后写入数据
                        Track track = new Track();
                        track.setNumber(i);
                        track.setName("#" + i);
                        track.setTrackPoints(wayPoints);
                        Route route = new Route();
                        route.setRoutePoints(wayPoints);
                        route.setName("#" + i);
                        route.setNumber(i);
                        GPX gpx = new GPX();
                        gpx.addTrack(track);
                        gpx.addRoute(route);
                        gpx.setVersion("v1");
                        GPXParser p = new GPXParser();
                        FileOutputStream out = new FileOutputStream(filePath);
                        p.writeGPX(gpx, out);
                        out.flush();
                        out.close();
                        Upload(activitvtiesData, pathRecordList.get(i), fileOut, uptime, thecout);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    Showinfo(thecout);
                }
            }
        } else {
            //提示无需要上传的数据
            showToast(getResources().getString(R.string.notnewdata));
        }

    }


    private void Upload(StravasTokenInfo activitvtiesData, PathRecord pathRecord, File file, final String uptime, final int thecout) {
        String aname = pathRecord.getExerciseMode() == ExerciseMode.Mode_RUN ? "run" : "ride";
        String activity_type = pathRecord.getExerciseMode() == ExerciseMode.Mode_RUN ? "Run" : "Ride";
        Map<String, RequestBody> maps = new HashMap<>();
        RequestBody name = RequestBody.create(MediaType.parse("text/plain"), aname);
        RequestBody client_secret = RequestBody.create(MediaType.parse("text/plain"), activitvtiesData.getAthlete().getId() + "");
        RequestBody data_type = RequestBody.create(MediaType.parse("text/plain"), "gpx");
        RequestBody trainer = RequestBody.create(MediaType.parse("text/plain"), "0");
        RequestBody commute = RequestBody.create(MediaType.parse("text/plain"), "0");
        RequestBody description = RequestBody.create(MediaType.parse("text/plain"), aname);
        RequestBody type = RequestBody.create(MediaType.parse("text/plain"), activity_type);
        maps.put("activity_type", type);
        maps.put("name", name);
        maps.put("external_id", client_secret);
        maps.put("data_type", data_type);
        maps.put("trainer", trainer);
        maps.put("commute", commute);
        maps.put("description", description);
        RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        MultipartBody.Part muPart = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
        NetWorkUtil.getInstance().getJstyleApi().Strvasuploads("Bearer " + activitvtiesData.getAccess_token(), muPart, maps).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<StravasUploads>() {
            @Override
            public void onSubscribe(Disposable d) { }
            @Override
            public void onNext(StravasUploads activitvtiesData) { }
            @Override
            public void onError(Throwable e) { }
            @Override
            public void onComplete() { }
        });
    }







    private void Showinfo(final int counts) {
        Log.e("sfsfff", count + "***" + counts);
        count++;
        setCount(count);
        if (count == counts) {
            Message message = new Message();
            message.what = 0;
            message.obj = "Strava";
            RxBus.getInstance().post(message);
            count = 0;
            up = null;
            savetime(uptime);//保存最后一次上传数据的时间
        } else {
            DecimalFormat df = new DecimalFormat("###0");
            Message message = new Message();
            message.what = 1;
            message.obj = df.format((100f / counts) * count) + "%";
            RxBus.getInstance().post(message);

        }
    }

}
